<?php

namespace app;

use app\common\exception\FailedException;
use app\common\library\Code;
use app\common\library\CustomLog;
use Next\VarDumper\Dumper;
use Next\VarDumper\DumperHandler;
use support\exception\Handler;
use taoser\exception\ValidateException;
use Throwable;
use Tinywan\Jwt\Exception\JwtTokenException;
use Tinywan\Jwt\Exception\JwtTokenExpiredException;
use Webman\Http\Request;
use Webman\Http\Response;

/**
 * Notes:全局异常捕捉
 * Class ExceptionHandler
 * @package app
 */
class ExceptionHandler extends Handler
{
    use DumperHandler;

    public function report(Throwable $exception)
    {
        if ($exception instanceof FailedException ||
            $exception instanceof ValidateException ||
            $exception instanceof Dumper ||
            $exception instanceof JwtTokenException ||
            $exception instanceof JwtTokenExpiredException) {
            return;
        }
        $logs = '';
        if ($request = \request()) {
            $logs = $request->getRealIp() . ' ' . $request->method() . ' ' . trim($request->fullUrl(), '/');
        }
        $this->logger->error($logs . PHP_EOL . $exception);
    }

    public function render(Request $request, Throwable $exception): Response
    {
        if ($exception instanceof Dumper) {
            return \response($this->convertToHtml($exception));
        }
        if ($exception instanceof FailedException ||
            $exception instanceof ValidateException) {
            return self::selfResponse($exception, 'intact', Code::FAILED);
        }
        if ($exception instanceof JwtTokenException ||
            $exception instanceof JwtTokenExpiredException) {
            return self::selfResponse($exception, 'intact');
        }

        if (getenv('API_RESPONSE')) {
            if (!getenv('APP_DEBUG')) {
                return self::selfResponse($exception);
            }
            return self::selfResponse($exception, 'dev');
        }
        //兜底的
        if ($exception instanceof Throwable) {
            // 记录错误日志
            CustomLog::eLog($exception);
            return json(['code'=>Code::SYSTEM_ERROR, 'msg'=>'系统异常']);
        }
        return parent::render($request, $exception);
    }

    private static function selfResponse($e, $model = 'safe', $code = '')
    {
        $data = [];
        switch ($model) {
            case 'safe':
                $data['code'] = Code::FAILED;
                $data['msg'] = '操作失败';
                break;
            case 'dev':
                $data['code'] = $e->getCode();
                $data['msg'] = '操作失败：' . ' 行号：' . $e->getLine() . '--文件：' . $e->getFile() . '--错误信息：' . $e->getMessage();
                break;
            case 'intact':
                $data['code'] = !empty($code) ? $code : $e->getCode();
                $data['msg'] = $e->getMessage();
                break;
        }
        $data['data'] = [];
        return json($data);
    }
}